import * as Utils from './utils.js';
import Point from '../utils/Point.js';

export function showElement(element, keepPointerEvents, delay) {
    if (!element) return;
    // force layout engine to compute elements current state
    getComputedStyle(element).opacity;

    var d = (delay || 500) + 'ms';

    if (!keepPointerEvents) element.style.pointerEvents = 'auto';
    element.style.transition = 'visibility 0ms, opacity ' + d;
    element.style.visibility = 'visible';
    element.style.opacity = '1';
}

export function hideElement(element, keepPointerEvents, delay) {
    var d = (delay || 500) + 'ms';

    if (!keepPointerEvents) element.style.pointerEvents = 'none';
    element.style.transition = 'visibility ' + d + ', opacity ' + d;
    element.style.visibility = 'hidden';
    element.style.opacity = '0';
}

export function hideAndRemoveElement(element, delay) {
    if (typeof element.removeTimer !== 'undefined') return;
    element.removeTimer = setTimeout(function() {
        element.parentNode.removeChild(element);
    }, delay || 500);
    hideElement(element, delay);
}

export function getContrastColor(color) {
    if (!color) return 'black';
    var values = Utils.colorToByteArray(color);
    var brightness = (values[0] * 299 + values[1] * 587 + values[2] * 114) / 1000;
    brightness += ((255 - brightness) * (255 - values[3])) / 255; // consider alpha channel
    return brightness > 125 ? 'black' : 'white';
}

export function getMouseOffset(event, target) {
    // returns cross browser cursor position relative to element
    if (!target) target = event.target || event.srcElement;
    var rect = target.getBoundingClientRect();

    var clientX = event.type.indexOf('touch') < 0 ? event.clientX : event.touches[0].clientX;
    var clientY = event.type.indexOf('touch') < 0 ? event.clientY : event.touches[0].clientY;

    return new Point(clientX - rect.left, clientY - rect.top);
}
export function getPointerPagePos(event) {
    var pageX = event.type.indexOf('touch') < 0 ? event.pageX : event.touches[0].pageX;
    var pageY = event.type.indexOf('touch') < 0 ? event.pageY : event.touches[0].pageY;

    return new Point(pageX, pageY);
}

export function getSamplingPoints(s) {
    var points = [];
    for (var i = 0; i < s.controlPoints.length - 3; i += 3) {
        var p0 = new Point(s.controlPoints[i].x, s.controlPoints[i].y);
        var p1 = new Point(s.controlPoints[i + 1].x, s.controlPoints[i + 1].y);
        var p2 = new Point(s.controlPoints[i + 2].x, s.controlPoints[i + 2].y);
        var p3 = new Point(s.controlPoints[i + 3].x, s.controlPoints[i + 3].y);

        var estimatedLength = 0;
        estimatedLength += p0.distance(p1);
        estimatedLength += p1.distance(p2);
        estimatedLength += p2.distance(p3);

        var steps = Math.min(0.5, 1 / (estimatedLength / 100)); // each 100 mm or smaller if necessary
        for (var p = steps; p < 1; p += steps) {
            var cx = 3 * (p1.x - p0.x);
            var bx = 3 * (p2.x - p1.x) - cx;
            var ax = p3.x - p0.x - cx - bx;

            var cy = 3 * (p1.y - p0.y);
            var by = 3 * (p2.y - p1.y) - cy;
            var ay = p3.y - p0.y - cy - by;

            var x = ax * Math.pow(p, 3) + bx * Math.pow(p, 2) + cx * p + p0.x;
            var y = ay * Math.pow(p, 3) + by * Math.pow(p, 2) + cy * p + p0.y;

            points.push(new Point(x, y));
        }
    }
    // points.unshift(new Point(s.startPoint().x, s.startPoint().y));
    // points.push(new Point(s.endPoint().x, s.endPoint().y));
    points.unshift(new Point(Utils.startPoint(s).x, Utils.startPoint(s).y));
    points.push(new Point(Utils.endPoint(s).x, Utils.endPoint(s).y));
    return points;
}

export function getPosition(s, progress) {
    // set default for straight paths
    var p1 = Utils.startPoint(s);
    var p2 = Utils.endPoint(s);

    if (progress <= 0) return p1;
    if (progress >= 100) return p2;

    var fineProgress = progress / 100;
    if (s.controlPoints.length > 2) {
        var lProgress = (s.length * progress) / 100;
        var lNow = 0,
            points = getSamplingPoints(s);
        for (var i = 1; i < points.length; i++) {
            var lLast = lNow;
            lNow += points[i - 1].distance(points[i]);
            if (lNow >= lProgress) {
                p1 = points[i - 1];
                p2 = points[i];
                fineProgress = (lProgress - lLast) / (lNow - lLast);
                break;
            }
        }
    }
    var x = p1.x + (p2.x - p1.x) * fineProgress;
    var y = p1.y + (p2.y - p1.y) * fineProgress;

    return new Point(x, y);
}

// =======================
Element.prototype.setDisplay = function(show) {
    this.style.display = show ? '' : 'none';
};

Element.prototype.setDisabled = function(state) {
    this.disabled = state;
};

Element.prototype.appendChildren = function(children) {
    for (var i = 0; i < children.length; i++) {
        this.appendChild(children[i]);
    }
};

Element.prototype.removeAllChildren = function() {
    // faster than this.innerHTML = "" AND will work in IE too!
    while (this.firstChild) this.removeChild(this.firstChild);
};

Element.prototype.addOption = function(value, bgColor) {
    var option = document.createElement('option');

    option.value = value;
    option.text = value;

    if (bgColor) {
        option.style.backgroundColor = bgColor;
        option.style.color = getContrastColor(bgColor);
    }
    this.appendChild(option);
};

Element.prototype.addOptions = function(values) {
    for (var i = 0; i < values.length; i++) this.addOption(values[i]);
};

Element.prototype.addTableData = function(data, rowIndex, width, colGap, rowGap, colSpan, rowSpan) {
    var td = document.createElement('td');
    if (typeof data !== 'string') {
        td.appendChild(data);

        // if (siteMap) // if not custom UI
        // {
        if (width) data.style.width = width + 'px';
        if (colGap) data.style.marginRight = colGap + 'px';
        if (rowGap) data.style.marginBottom = rowGap + 'px';
        // }
        // else
        // {
        //     if (width) data.style.width = (width / 3.5) + "vmin";
        //     if (colGap) data.style.marginRight = "2vmin";
        //     if (rowGap) data.style.marginBottom = "2vmin";
        // }
    } else td.innerHTML = data;

    if (colSpan) td.setAttribute('colSpan', colSpan);
    if (rowSpan) td.setAttribute('rowSpan', rowSpan);

    // tbody instead of table because of IE and Edge
    var tbody = this.querySelector('tBody');
    if (!tbody) {
        tbody = document.createElement('tbody');
        var table = document.createElement('table');
        table.appendChild(tbody);
        this.appendChild(table);
    }
    var tr = tbody.children[rowIndex];
    if (!tr) {
        tr = document.createElement('tr');
        tbody.appendChild(tr);
    }
    tr.appendChild(td);
};

Element.prototype.hasNumbersOnly = function() {
    return !isNaN(parseFloat(this.value)) && isFinite(this.value);
};

// Object.prototype.startPoint = function ()
// {
//     if (this.controlPoints) return this.controlPoints[0];
// };

// Object.prototype.endPoint = function ()
// {
//     if (this.controlPoints) return this.controlPoints[this.controlPoints.length - 1];
// };
